home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / ka9q_src.arc / NR3.C < prev    next >
C/C++ Source or Header  |  1988-07-28  |  22KB  |  838 lines

  1. /* cat > ./nr3.c << '\Rogue\Monster\' */
  2. /* net/rom level 3 low level processing */
  3.  
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "timer.h"
  9. #include "arp.h"
  10. #include "slip.h"
  11. #include "ax25.h"
  12. #include "netrom.h"
  13. #include "lapb.h"
  14. #include <ctype.h>
  15.  
  16. /* Nodes message broadcast address: "NODES" in shifted ASCII */
  17. struct ax25_addr nr_nodebc = {
  18.     'N'<<1, 'O'<<1, 'D'<<1, 'E'<<1, 'S'<<1, ' '<<1,
  19.     ('0'<<1) | E
  20. } ;
  21.  
  22. struct nriface nrifaces[NRNUMIFACE] ;
  23. unsigned nr_numiface ;
  24. struct nrnbr_tab *nrnbr_tab[NRNUMCHAINS] ;
  25. struct nrroute_tab *nrroute_tab[NRNUMCHAINS] ;
  26. struct nrnf_tab *nrnf_tab[NRNUMCHAINS] ;
  27. unsigned nr_nfmode = NRNF_NOFILTER ;
  28. unsigned nr_ttl = 64 ;
  29. unsigned obso_init = 6 ;
  30. unsigned obso_minbc = 5 ;
  31. unsigned nr_maxroutes = 5 ;
  32. unsigned nr_autofloor = 1 ;
  33. struct interface *nr_interface ;
  34.  
  35. /* send IP datagrams across a net/rom network connection */
  36. int
  37. nr_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  38. struct mbuf *bp ;
  39. struct interface *interface ;
  40. int32 gateway ;
  41. char precedence ;
  42. char delay ;
  43. char throughput ;
  44. char reliability ;
  45. {
  46.     struct ax25_addr dest ;
  47.     struct mbuf *tbp, *htonnr3() ;
  48.     struct nr3hdr n3hdr ;
  49.     char *hwaddr ;
  50.     struct arp_tab *arp ;
  51.  
  52.     if ((arp = arp_lookup(ARP_NETROM,gateway)) == NULLARP) {
  53.         free_p(bp) ;    /* drop the packet if no route */
  54.         return ;
  55.     }
  56.     hwaddr = arp->hw_addr ;                /* points to destination */
  57.     memcpy(dest.call, hwaddr, ALEN) ;
  58.     dest.ssid = hwaddr[ALEN] ;
  59.         
  60.     /* set up host format header */
  61.     /* The null source call is a signal to nr_route to insert the call */
  62.     /* of the outbound interface.  We can't do it here because */
  63.     /* we don't know the interface it's going to go out, and */
  64.     /* the interfaces might have different callsigns.       */
  65.     n3hdr.source.call[0] = '\0' ;
  66.     n3hdr.dest = dest ;
  67.     n3hdr.ttl = nr_ttl ;
  68.  
  69.     /* Convert to a network format header.  This will be stripped */
  70.     /* back off in nr_route, but them's the breaks.               */
  71.     if ((tbp = htonnr3(&n3hdr)) == NULLBUF) {
  72.         free_p(bp) ;
  73.         return ;
  74.     }
  75.     append(tbp,bp) ;        /* append data to header */
  76.     nr_route(tbp) ;            /* pass off to level 3 routing code */
  77.  
  78. }
  79.  
  80. /* Figure out if a call is assigned to one of my net/rom
  81.  * interfaces.
  82.  */
  83. static int
  84. ismycall(addr)
  85. struct ax25_addr *addr ;
  86. {
  87.     register int i ;
  88.     int found = 0 ;
  89.     
  90.     for (i = 0 ; i < nr_numiface ; i++)
  91.         if (addreq((struct ax25_addr *)(nrifaces[i].interface->hwaddr),
  92.             addr)) {
  93.             found = 1 ;
  94.             break ;
  95.         }
  96.  
  97.     return found ;
  98. }
  99.  
  100.  
  101. /* Route net/rom network layer packets.
  102.  */
  103. nr_route(bp)
  104. struct mbuf *bp ;
  105. {
  106.     struct nr3hdr n3hdr ;
  107.     struct ax25_cb *axp, *find_ax25(), *open_ax25() ;
  108.     struct ax25 naxhdr ;
  109.     struct ax25_addr neighbor ;
  110.     struct mbuf *hbp, *pbp, *htonnr3() ;
  111.     extern int16 axwindow ;
  112.     void ax_incom() ;
  113.     register struct nrnbr_tab *np ;
  114.     register struct nrroute_tab *rp ;
  115.     register struct nr_bind *bindp, *find_best() ;
  116.     struct interface *interface ;
  117.     
  118.     if (ntohnr3(&n3hdr,&bp) == -1) {
  119.         free_p(bp) ;
  120.         return ;
  121.     }
  122.  
  123.     if (ismycall(&n3hdr.dest)) {
  124.         ip_route(bp,0) ;
  125.         return ;
  126.     }
  127.  
  128.     if ((rp = find_nrroute(&n3hdr.dest)) == NULLNRRTAB) {
  129.         /* no route, drop the packet */
  130.         free_p(bp) ;
  131.         return ;
  132.     }
  133.  
  134.     if ((bindp = find_best(rp->routes,1)) == NULLNRBIND) {
  135.         /* This shouldn't happen yet, but might if we add */
  136.         /* dead route detection */
  137.         free_p(bp) ;
  138.         return ;
  139.     }
  140.  
  141.     np = bindp->via ;
  142.     memcpy(neighbor.call,np->call,ALEN) ;
  143.     neighbor.ssid = np->call[ALEN] ;
  144.     interface = nrifaces[np->interface].interface ;
  145.  
  146.     /* Now check to see if the source call is null.  That is */
  147.     /* a signal from nr_send that the packet originates here, */
  148.     /* so we need to insert the callsign of the appropriate  */
  149.     /* interface */
  150.     if (n3hdr.source.call[0] == '\0')
  151.         memcpy(&n3hdr.source,interface->hwaddr,AXALEN) ;
  152.     
  153.     /* Make sure there is a connection to the neighbor */
  154.     if ((axp = find_ax25(&neighbor)) == NULLAX25 || axp->state != CONNECTED) {
  155.         /* Open a new connection or reinitialize old one */
  156.         /* hwaddr has been advanced to point to neighbor + digis */
  157.         atohax25(&naxhdr, np->call, (struct ax25_addr *)interface->hwaddr) ;
  158.         axp = open_ax25(&naxhdr, axwindow, ax_incom, NULLVFP, NULLVFP,
  159.                         interface,(char *)0) ;
  160.         if (axp == NULLAX25) {
  161.             free_p(bp) ;
  162.             return ;
  163.         }
  164.     }
  165.         
  166.     if (--n3hdr.ttl == 0) {    /* the packet's time to live is over! */
  167.         free_p(bp) ;
  168.         return ;
  169.     }
  170.  
  171.     /* allocate and fill PID mbuf */
  172.     if ((pbp = alloc_mbuf(1)) == NULLBUF) {
  173.         free_p(bp) ;
  174.         return ;
  175.     }
  176.     pbp->cnt = 1 ;
  177.     *pbp->data = (PID_FIRST | PID_LAST | PID_NETROM) ;
  178.  
  179.     /* now format network header */
  180.     if ((hbp = htonnr3(&n3hdr)) == NULLBUF) {
  181.         free_p(pbp) ;
  182.         free_p(bp) ;
  183.         return ;
  184.     }
  185.  
  186.     append(pbp,hbp) ;        /* append header to pid */
  187.     append(pbp,bp) ;        /* append data to header */
  188.     send_ax25(axp,pbp) ;    /* pass it off to ax25 code */
  189. }
  190.     
  191.  
  192. /* Perform a nodes broadcast on interface # ifno in the net/rom
  193.  * interface table.
  194.  */
  195.  
  196. nr_bcnodes(ifno)
  197. unsigned ifno ;
  198. {
  199.     struct mbuf *hbp, *dbp, *savehdr ;
  200.     struct nrroute_tab *rp ;
  201.     struct nrnbr_tab *np ;
  202.     struct nr_bind * bp ;
  203.     struct nr3dest nrdest ;
  204.     int i, didsend = 0, numdest = 0 ;
  205.     register char *cp ;
  206.     struct interface *axif = nrifaces[ifno].interface ;
  207.     
  208.     /* prepare the header */
  209.     if ((hbp = alloc_mbuf(NR3NODEHL)) == NULLBUF)
  210.         return ;
  211.         
  212.     hbp->cnt = NR3NODEHL ;    
  213.     
  214.     *hbp->data = NR3NODESIG ;
  215.     memcpy(hbp->data+1,nrifaces[ifno].alias,ALEN) ;
  216.  
  217.     /* make a copy of the header in case we need to send more than */
  218.     /* one packet */
  219.     savehdr = copy_p(hbp,NR3NODEHL) ;
  220.  
  221.     /* now scan through the routing table, finding the best routes */
  222.     /* and their neighbors.  create destination subpackets and append */
  223.     /* them to the header */
  224.     for (i = 0 ; i < NRNUMCHAINS ; i++) {
  225.         for (rp = nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
  226.             /* look for best, non-obsolescent route */
  227.             if ((bp = find_best(rp->routes,0)) == NULLNRBIND)
  228.                 continue ;    /* no non-obsolescent routes found */
  229.             if (bp->quality == 0)    /* this is a loopback route */
  230.                 continue ;            /* we never broadcast these */
  231.             np = bp->via ;
  232.             /* insert best neighbor */
  233.             memcpy(nrdest.neighbor.call,np->call,ALEN) ;
  234.             nrdest.neighbor.ssid = np->call[ALEN] ;
  235.             /* insert destination from route table */
  236.             nrdest.dest = rp->call ;
  237.             /* insert alias from route table */
  238.             strcpy(nrdest.alias,rp->alias) ;
  239.             /* insert quality from binding */
  240.             nrdest.quality = bp->quality ;
  241.             /* create a network format destination subpacket */
  242.             if ((dbp = htonnrdest(&nrdest)) == NULLBUF) {
  243.                 free_p(hbp) ;    /* drop the whole idea ... */
  244.                 free_p(savehdr) ;
  245.                 return ;
  246.             }
  247.             append(hbp,dbp) ;    /* append to header and others */
  248.             /* see if we have appended as many destinations */
  249.             /* as we can fit into a single broadcast.  If we */
  250.             /* have, go ahead and send them out. */
  251.             if (++numdest == NRDESTPERPACK) {    /* filled it up */
  252.                 didsend = 1 ;    /* indicate that we did broadcast */
  253.                 numdest = 0 ;    /* reset the destination counter */
  254.                 (*axif->output)(axif, (char *)&nr_nodebc, axif->hwaddr,
  255.                                  (PID_FIRST | PID_LAST | PID_NETROM),
  256.                                  hbp) ;    /* send it */
  257.                 hbp = copy_p(savehdr,NR3NODEHL) ;    /* new header */
  258.             }
  259.         }
  260.     }
  261.  
  262.     /* Now, here is something totally weird.  If our interfaces */
  263.     /* have different callsigns than this one, advertise a very */
  264.     /* high quality route to them.  Is this a good idea?  I don't */
  265.     /* know.  However, it allows us to simulate a bunch of net/roms */
  266.     /* hooked together with a diode matrix coupler. */
  267.     for (i = 0 ; i < nr_numiface ; i++) {
  268.         if (i == ifno)
  269.             continue ;        /* don't bother with ours */
  270.         cp = nrifaces[i].interface->hwaddr ;
  271.         if (!addreq((struct ax25_addr *)axif->hwaddr,cp)) {
  272.             /* both destination and neighbor address */
  273.             memcpy(&nrdest.dest,cp,AXALEN) ;
  274.             memcpy(&nrdest.neighbor,cp,AXALEN) ;
  275.             /* alias of the interface */
  276.             strcpy(nrdest.alias,nrifaces[i].alias) ;
  277.             /* and the very highest quality */
  278.             nrdest.quality = 255 ;
  279.             /* create a network format destination subpacket */
  280.             if ((dbp = htonnrdest(&nrdest)) == NULLBUF) {
  281.                 free_p(hbp) ;    /* drop the whole idea ... */
  282.                 free_p(savehdr) ;
  283.                 return ;
  284.             }
  285.             append(hbp,dbp) ;    /* append to header and others */
  286.             if (++numdest == NRDESTPERPACK) {    /* filled it up */
  287.